<?php namespace models;
use helpers\Helper as Helper;
/**
 * This code is property of Piotr Poradzisz. Do not distribute under threat of legal consequences.
 * All rights reserved.
 * Все права защищены.
 * Alle Rechte vorbehalten.
 * Todos los derechos reservados.
 * Wszelkie prawa zastrzeżone.
 *                  جميع الحقوق محفوظة
 * 保留所有权利
 * すべての著作権
 * @author Piotr Poradzisz
 * email: piotr.poradzisz@gmail.com
 * tel.: +48668027020
 */
define(ImageSufixSmall, 's');
define(ImageSufixBig, 'b');

class File extends Field{

    public $referenceTable;
    
    protected $name;

    public $uploadPath = '../upload';

    public function setParams($fileName){
         // obsługa nazwy pliku i rozszerzenia
        $path_info = pathinfo($fileName);
        $this->fileName = strtolower(Helper::convertToPath($path_info['filename']));
        $this->ext = strtolower($path_info['extension']);
        $this->fileType = $this->PrivGetFileType($this->ext);
        $this->from = $_SESSION['query']['from'];
    }


    public function upload($fileName, $fieldId=null, $itemId=null){
       
        $this->setParams($fileName);

        $this->setFileRange($fieldId);
        
        $this->newPath = $this->getNewPath($this->fileType);

        // odczyt numeru porzadkowego dla nowego zdjecia
        $mysql = new Mysql();

        if($this->relation == 3)
        {
            // jezeli lista
            $query = "  SELECT count(*) FROM $this->referenceTable WHERE name LIKE '$this->fileName%'";
        }

        else if($this->relation == 1)
        {
            //jezeli pojedynczy plik z kolumny w obslugiwanej tabeli
            $file['fileType'] = $this->fileType;
            $file['name'] = $this->fileName;
            $file['ext'] = $this->ext;
            $this->fileDelete($file);
            $query = "  SELECT count(*) FROM $this->from WHERE $this->name LIKE '$this->fileName%'  ";
        }
        
        $nr = $mysql->getRecord($query);
        $nr = ($nr == 0 ? null : "_$nr");
        $new_name = $this->fileName.$nr;
        // jezeli nie istnieje docelowa ścieżka to utwórz
        if(!file_exists($this->newPath)) mkdir($this->newPath);
        // jezeli plik typu zdjecie
        if($this->fileType == 1){
            $image = new Image($fileName, $this->uploadPath);
            $image->name = $this->fileName;
            $image->ext = $this->ext;
            $image->resize($_POST['size'], $new_name, $this->newPath);
        }
        // jezeli jakikolwiek inny plik nie wymagający konwersji to skopiuj z nową nazwą
        else{
          copy("$this->uploadPath/$fileName", "$this->newPath/$new_name.$this->ext");
        }

        if($this->relation == 3){
             //określenie pozycji w kolejności dla nowego, lokalnego pliku
            if($fieldId != 'global'){
                $query = "SELECT MAX(position) FROM  $this->referenceTable WHERE parent = $itemId";
                $maxPosition = $mysql->getRecord($query);
                if($maxPosition < 1) $maxPosition = 0;
                // zapisanie parametrów pliku lokalnego
                $query = "INSERT INTO $this->referenceTable (parent, name, fileType, ext, position) VALUES  ($itemId, '$new_name', $this->fileType, '$this->ext', $maxPosition) ";
            }
            // zapisanie parametrów pliku globalnego
            else{
                $query = "INSERT INTO $this->referenceTable (name, fileType, ext) VALUES  ('$new_name', $this->fileType, '$this->ext') ";
            }
            $mysql->setQuery($query);

            // pobranie parametrów osostanio dodanego zdjęcia w celu wyświetlenia go
            $newFile = $this->getFiles('id = last_insert_id()');
            $this->newFile = $newFile[0];
        }
        else if($this->relation == 1){
            $query = "UPDATE $this->from SET $this->name = '$new_name.$this->ext' WHERE id = $itemId";
            $mysql->setQuery($query);
            $this->newFile['fileType'] = $this->fileType;
            $this->newFile['ext'] = $this->ext;
            $this->newFile['name'] = $this->fileName;
            $this->newFile['id'] = $itemId;
        }      

        // zwrócenie realnych rozmiarów zdjęcia na wypadek jakby żądane wymiary były większe niż wymiary zdjęcia źródłowego
        if(isset($image->size)) $this->newFile['size'] = $image->size;
        $this->newFile['path'] = $this->newPath;
        // po wszytskim usunięcie niepotrzebnego, orginalnego zdjęcia
        unlink("$this->uploadPath/$fileName");
    }

    public function read($fileType=null, $itemId = null, $fieldId = null){
        //jezeli plik dostępu globalnego
        if($itemId == null){
            $this->newPath = '../upload/global';
            $this->referenceTable = 'globalFiles';
            $where = ($fileType == null ? null : "fileType = $fileType");
            $files = $this->getFiles($where, 'name');
        }
        // jezeli plik dostępu lokalnego
        else{
            $where = ($fileType == null ? null : "fileType = $fileType AND");
            $this->newPath = '../upload';
            $this->setFieldProperties($fieldId, array('referenceTable', 'name'));
            if($this->referenceTable)
            {
                $files = $this->getFiles("$where parent = $itemId", 'position');
            }
            else
            {
                $files = $this->getFiles("$where id = $itemId");
            }
        }        
        
        foreach($files as $fileKey => $file){
            if($file['name'])
            {                
                $FileName = $file['name'];
                $FileExtension = $file['ext'];
            }
            else
            {
                $File = $file[$this->name];
                $FileExtension = end(explode('.', $File));
                $FileName = str_replace('.'.$FileExtension, null, $File);
                $files[$fileKey]['name'] = $FileName;
                $files[$fileKey]['ext'] = $FileExtension;
            }
            
            $FileType = $this->PrivGetFileType($FileExtension);   
            $files[$fileKey]['fileType'] = $FileType;
            $path = $this->getNewPath($FileType);
            // jezeli zdjęcie to pobranie realnych wymiarów 
            if($FileType == 1){
                $SmallImagePath = $path.'/'.$FileName.'_'.ImageSufixSmall.'.'.$FileExtension;
                $BigImagePath = $path.'/'.$FileName.'_'.ImageSufixBig.'.'.$FileExtension;
                if(file_exists($SmallImagePath)) $files[$fileKey]['size'][ImageSufixSmall] = getimagesize($SmallImagePath);
                if(file_exists($BigImagePath)) $files[$fileKey]['size'][ImageSufixBig] = getimagesize($BigImagePath);
            }
 
            $files[$fileKey]['path'] = $path;
            // w celu uproszczenia tpl od zdjecia uspójnienie pomiędzy odczytem z formularzem a odczytem po dodaniu zdjęcia 
            $_POST['fieldId'] = $fieldId;
        }
        return $files;
    }

    public function delete($id, $fieldId = null, $all = false){
        $mysql = new Mysql();
        // jezeli plik dostępu globalnego
        $this->setFileRange($fieldId);
        if($this->relation == 1){
            $query = "UPDATE $this->from SET $this->name = null WHERE id = $id";
            $file['name'] = $this->fileName;
            $file['ext'] = $this->ext;
            $file['fileType'] = $this->fileType;
            $this->fileDelete($file);
        }
        else{
            if($fieldId == 'global'){

                $file = $this->getFiles("id = $id");
                $query = "DELETE FROM $this->referenceTable WHERE id = $id";
                $mysql->setQuery($query);

                $this->fileDelete($file[0]);
            }
            // jezeli plik dostępu lokalnego
            else{

                // jezeli usunięcie tylko jednego pliku
                if($all !== true){
                    $file = $this->getFiles("id = $id");
                    $query = "DELETE FROM $this->referenceTable WHERE id = $id";
                    $mysql->setQuery($query);

                    $this->fileDelete($file[0]);
                }
                // jezeli usunięcie wszystkich plików np. przy usówaniu całego subject
                else{
                    $files = $this->getFiles("parent = $id");
                    $query = "DELETE FROM $this->referenceTable WHERE parent = $id";
                    $mysql->setQuery($query);
                    foreach($files as $file){
                        $this->fileDelete($file);
                    }
                }
            }
        }
    }

    private function fileDelete($file){
        $path = $this->getNewPath($file['fileType']);

        // jezeli zdjecie
        if($file['fileType'] == 1){
            $files = glob("$path/$file[name]"."_?.*");
            array_map('unlink', $files);
        }
        // jezeli zwykły plik
        else{
            unlink("$path/$file[name].$file[ext]");
        }
    }

    private function getFileType($ext)
    {
        if($ext=='jpg' or $ext=='jpeg' or $ext=='gif' or $ext=='png' or $ext=='tif' or $ext=='tiff' or $ext=='bmp')
        {
            return 1;
        }
        else if($ext=='mp3' or $ext=='wav' or $ext=='flac' or $ext=='amr' or $ext=='ogg')
        {
            return 2;
        }
        else if($ext=='doc' or $ext=='docx' or $ext=='xls'  or $ext=='pdf' or $ext=='odt' or $ext=='odx')
        {
            return 3;
        }
        else if($ext=='flv' or $ext=='swf')
        {
            return 4;
        }
        else if($ext=='avi' or $ext=='mpg' or $ext=='mpeg' or $ext=='mp4' or $ext=='mov')
        {
            return 5;
        }
        else
        {
            return 9;
        }
    }
    
    private function PrivGetFileType($FileExtension)
    {        
        switch($FileExtension)
        {
            case 'jpg' : case 'jpeg': case 'gif' : case 'png' : case 'tif' : case 'tiff': case 'bmp' : 
            return 1;
        
            case 'mp3' : case 'wav' : case 'flac': case 'amr' : case 'ogg' :
            return 2;                
        
            case 'doc' : case 'docx': case 'xls' : case 'pdf' : case 'odt' : case 'odx' :
            return 3;
        
            case 'flv' : case 'swf' :
            return 4;
        
            case 'avi' : case 'mpg' : case 'mpeg': case 'mp4' : case 'mov' :
            return 5;
        
            default    :
            return 9;
        }      
    }

    private function getNewPath($fileType)
    {
        switch ($fileType)
        {
            case 1: return "$this->newPath/images";
            case 2: return "$this->newPath/music";
            case 3: return "$this->newPath/documents";
            case 4: return "$this->newPath/flesh";
            case 5: return "$this->newPath/video";
            case 9: return "$this->newPath/other";
        }
    }  

    public function imageRotate($id, $fieldId = null)
    {
        $this->setFileRange($fieldId);
        $this->newPath .= '/images';
        $file = $this->getFiles("id = $id");
        $image = new Image($file[0], $this->newPath);
        $image->rotate();        
        $this->newFile = $image->file;
    }

    public function getFiles($where = null, $orderBy = null){
        $mysql = new Mysql();
        $where = ($where == null ? null : "WHERE $where");
        $orderBy = ($orderBy == null ? null : "ORDER BY $orderBy");
        if($this->referenceTable)
        {
            $query = "SELECT * FROM $this->referenceTable $where $orderBy";
        }
        else
        {
            $this->from = $_SESSION['query']['from'];
            $query = "SELECT $this->name FROM $this->from $where ";
        }
        return $mysql->getTable($query);        
    }
    /**
     *  Metoda ustawiająca scieżke oraz tablelę z plikami na podstawie tego czy plik lokalny czy globalny
     * @param <int> $fieldId parametr wskazuje czy plik lokalny czy globalny
     */
    private function setFileRange($fieldId = null){
        if($fieldId == 'global'){
            $this->relation = 3;
            $this->newPath = '../upload/global';
            $this->referenceTable = 'globalFiles';
        }
        // jezeli plik dostępu lokalnego
        else{
            $this->newPath = '../upload';
            $this->setFieldProperties($fieldId, array('referenceTable','multiple', 'name', 'tableName', 'relation'));
        }
    }

    public static function getFileTypes($id = null, $filedId = null){
        $mysql = new Mysql();
        $where = ($id == null ? null : " WHERE id = $id");
        if($filedId == null) $query = 'SELECT * FROM fileType'.$where;
        else $query = "SELECT ft.* FROM fileType ft JOIN field_fileType fft ON fft.childe = ft.id WHERE fft.parent = $filedId";
        return $mysql->getTable($query);
    }


    public function setFileAlt($id, $fieldId, $alt) {
        $mysql = new Mysql();
        $this->setFileRange($fieldId);
        $query = "UPDATE $this->referenceTable SET alt = '$alt' WHERE id = $id";
        $mysql->setQuery($query);
    }
    public function getFile($id, $fieldId){
       $this->setFileRange($fieldId);
       $files = $this->getFiles("id = $id");
       return $files[0];
    }

    public function getJSON($id, $fieldId){
        return json_encode($this->getFile($id, $fieldId));
    }
}
?>